/*
 * MadHelix is a Java Swing-based GUI frontend for SoundHelix.
 * Copyright (C) 2017-2019, 2023 UltrasonicMadness
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 only,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.ultrasonicmadness.madhelix.models;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.xml.sax.SAXException;

import org.ultrasonicmadness.madhelix.utils.PathUtils;

public class HistoryTableModel extends AbstractTableModel {
    private final String HISTORY_PATH = PathUtils.getHistoryPath();
    private ArrayList<SongEntry> history = null;

    public HistoryTableModel() throws IOException, XMLStreamException {
        try {
            File historyFile = new File(HISTORY_PATH);

            SongHistoryHandler handler = new SongHistoryHandler();
            SAXParserFactory.newInstance().newSAXParser().parse(historyFile,
                    handler);
            history = handler.getHistory();
        } catch (ParserConfigurationException | SAXException |
                FileNotFoundException x) {
            history = new ArrayList<>();
        }
    }

    @Override
    public int getRowCount() {
        return history.size();
    }

    @Override
    public int getColumnCount() {
        return 4;
    }

    @Override
    public String getColumnName(int col) {
        switch(col) {
            case 0:
                return "Song name";

            case 1:
                return "Style";

            case 2:
                return "Length";

            case 3:
                return "Time played";

            default:
                return null;
        }
    }

    @Override
    public Object getValueAt(int row, int col) {
        switch(col) {
            case 0:
                return history.get(row).SONG_NAME;

            case 1:
                return history.get(row).STYLE_NAME;

            case 2:
                return history.get(row).getLengthAsString();

            case 3:
                return history.get(row).getTimePlayedAsString();

            default:
                return null;
        }
    }

    public void logSong(String songName, String style, int length)
            throws IOException, XMLStreamException {
        long timestamp = Instant.now().getEpochSecond();
        history.add(0, new SongEntry(songName, style, length, timestamp));

        writeToLogFile();

        fireTableDataChanged();
    }

    private void writeToLogFile() throws IOException, XMLStreamException {
        FileWriter writer = new FileWriter(PathUtils.getHistoryPath());

        XMLStreamWriter xml = XMLOutputFactory.newFactory()
                .createXMLStreamWriter(writer);

        xml.writeStartDocument();
        xml.writeCharacters("\n");
        xml.writeStartElement("madhelix-history");
        xml.writeCharacters("\n");

        for (SongEntry entry : history) {
            xml.writeCharacters("  ");
            xml.writeEmptyElement("entry");
            xml.writeAttribute("name", entry.SONG_NAME);
            xml.writeAttribute("style", entry.STYLE_NAME);
            xml.writeAttribute("length", Integer.toString(entry.LENGTH));
            xml.writeAttribute("timestamp", Long.toString(entry.TIMESTAMP));
            xml.writeCharacters("\n");
        }

        xml.writeEndElement();
        xml.writeCharacters("\n");
        xml.writeEndDocument();

        xml.close();
        writer.close();
    }

    public void clear() {
        history.clear();
        fireTableDataChanged();
    }
}
